package mapper

import (
	"context"
	"gorm.io/gorm"
	"mall/services/product/rpc/internal/domain/bo"
	"mall/services/product/rpc/internal/initialize/mysql"
	"mall/services/product/rpc/internal/mapper/entity"
	"time"
)

var categoryAllColumn = "category_id, create_time, update_time, shop_id, parent_id, name, `desc`," +
	"path, status, icon, img_url, level, seq"

type CategoryMapper struct {
	ctx context.Context
}

func NewCategoryMapper(ctx context.Context) *CategoryMapper {
	return &CategoryMapper{ctx: ctx}
}
func (m *CategoryMapper) SelectCountCtx(db *gorm.DB, categoryBO bo.CategoryBO) (totalCount int64, err error) {
	// 监控
	_, span := mysql.StartSpan(m.ctx, "CategoryMapper#SelectCountCtx")
	defer func() {
		mysql.EndSpan(span, err)
	}()
	tx := db.Session(&gorm.Session{SkipDefaultTransaction: true})

	var total int64
	categoryEntity := entity.CategoryEntity{}
	tx = tx.Select(categoryAllColumn).Table(categoryEntity.TableName())
	m.getAllWhereSql(tx, categoryBO)
	tx = tx.Count(&total)
	return total, tx.Error
}

func (m *CategoryMapper) SelectOneCtx(db *gorm.DB, categoryBO bo.CategoryBO) (category entity.CategoryEntity, err error) {
	// 监控
	_, span := mysql.StartSpan(m.ctx, "CategoryMapper#SelectOneCtx")
	defer func() {
		mysql.EndSpan(span, err)
	}()
	tx := db.Session(&gorm.Session{SkipDefaultTransaction: true})
	var categoryEntity entity.CategoryEntity
	tx = tx.Select(categoryAllColumn).Table(categoryEntity.TableName())
	m.getAllWhereSql(tx, categoryBO)
	tx = tx.First(&categoryEntity)
	if tx.Error != nil && tx.Error.Error() == "record not found" {
		return categoryEntity, nil
	}
	return categoryEntity, tx.Error
}

func (m *CategoryMapper) SelectListCtx(db *gorm.DB, categoryBO bo.CategoryBO) (categoryArr []entity.CategoryEntity, err error) {
	// 监控
	_, span := mysql.StartSpan(m.ctx, "CategoryMapper#SelectListCtx")
	defer func() {
		mysql.EndSpan(span, err)
	}()
	tx := db.Session(&gorm.Session{SkipDefaultTransaction: true})
	tx = tx.Select(categoryAllColumn).Table("category")
	m.getAllWhereSql(tx, categoryBO)
	tx = tx.Find(&categoryArr)
	return categoryArr, tx.Error
}

func (m *CategoryMapper) getAllWhereSql(db *gorm.DB, categoryBO bo.CategoryBO) {
	if categoryBO.CategoryId > 0 {
		db.Where("category_id = ?", categoryBO.CategoryId)
	}
	if len(categoryBO.CategoryIdArr) > 0 {
		db.Where("category_id in ?", categoryBO.CategoryIdArr)
	}
	if categoryBO.ShopId != 0 {
		db.Where("shop_id = ?", categoryBO.ShopId)
	}
	if categoryBO.ParentId != 0 {
		db.Where("parent_id = ?", categoryBO.ParentId)
	}
	if len(categoryBO.Name) > 0 {
		db.Where("name = ?", categoryBO.Name)
	}
	if len(categoryBO.NameAllLike) > 0 {
		db.Where("name like ?", "%"+categoryBO.Name+"%")
	}
	if len(categoryBO.Desc) > 0 {
		db.Where("desc = ?", categoryBO.Desc)
	}
	if len(categoryBO.Path) > 0 {
		db.Where("path = ?", categoryBO.Path)
	}
	if categoryBO.Status != 0 {
		db.Where("status = ?", categoryBO.Status)
	}
	if categoryBO.NeStatus != 0 {
		db.Where("status != ?", categoryBO.NeStatus)
	}
	if len(categoryBO.Icon) > 0 {
		db.Where("icon = ?", categoryBO.Icon)
	}
	if len(categoryBO.ImgUrl) > 0 {
		db.Where("img_url = ?", categoryBO.ImgUrl)
	}
	if categoryBO.Level != 0 {
		db.Where("level = ?", categoryBO.Level)
	}
	if categoryBO.Seq != 0 {
		db.Where("seq = ?", categoryBO.Seq)
	}
}

func (m *CategoryMapper) CategoryManage(engin *gorm.DB, categoryIdArr []int64, status int32) (err error) {
	// 监控
	_, span := mysql.StartSpan(m.ctx, "CategoryMapper#CategoryManage")
	defer func() {
		mysql.EndSpan(span, err)
	}()
	if len(categoryIdArr) <= 0 {
		// 不存在直接返回
		return nil
	}
	spuEntity := entity.CategoryEntity{}
	tx := engin.Table(spuEntity.TableName()).Where("category_id in ?", categoryIdArr).
		Omit("category_id").Update("status", status).
		Update("update_time", time.Now())
	return tx.Error
}

func (m *CategoryMapper) UpdateCtx(engin *gorm.DB, categoryEntity entity.CategoryEntity) (err error) {
	// 监控
	_, span := mysql.StartSpan(m.ctx, "CategoryMapper#UpdateCtx")
	defer func() {
		mysql.EndSpan(span, err)
	}()
	tx := engin.Where("sku_id = ?", categoryEntity.CategoryId).Omit("category_id").
		UpdateColumns(categoryEntity)
	return tx.Error
}

func (m *CategoryMapper) InsertCtx(engin *gorm.DB, categoryEntity entity.CategoryEntity) (categoryId int64, err error) {
	// 监控
	_, span := mysql.StartSpan(m.ctx, "CategoryMapper#InsertCtx")
	defer func() {
		mysql.EndSpan(span, err)
	}()
	tx := engin.Create(&categoryEntity)
	return categoryEntity.CategoryId, tx.Error
}
